package cn.boysoft.module.security.manager.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import cn.boysoft.core.Constants;
import cn.boysoft.core.ServiceCode;
import cn.boysoft.core.annotation.JEEResultConvert;
import cn.boysoft.core.annotation.JEEService;
import cn.boysoft.core.convert.impl.EntityToIdConvert;
import cn.boysoft.core.exception.JEEException;
import cn.boysoft.core.manager.impl.ManagerImpl;
import cn.boysoft.core.model.PageParam;
import cn.boysoft.core.model.Tree;
import cn.boysoft.core.model.TreeNode;
import cn.boysoft.module.security.manager.ResourceManager;
import cn.boysoft.module.security.manager.UserManager;
import cn.boysoft.module.security.model.entity.OrgEntity;
import cn.boysoft.module.security.model.entity.PostEntity;
import cn.boysoft.module.security.model.entity.ResourceEntity;
import cn.boysoft.module.security.model.entity.ResourceTypeEnum;
import cn.boysoft.module.security.model.entity.RoleEntity;
import cn.boysoft.module.security.model.entity.UserEntity;
import cn.boysoft.module.security.model.vo.LoginParam;
import cn.boysoft.module.security.model.vo.LoginResult;
import cn.boysoft.module.security.model.vo.MenuNode;
import cn.boysoft.module.security.model.vo.UserPageParam;
/**
 * @author 付厚俊
 * CreateTime 2013-4-5 上午10:29:52
 */
@Service(value="userManager")
@Transactional
public class UserManagerImpl extends ManagerImpl<UserEntity,UserPageParam> implements UserManager<UserEntity,UserPageParam> ,ServiceCode{
	private final static Logger LOGGER = LoggerFactory.getLogger(RoleManagerImpl.class);
	public final static String CODE="02";
	@Autowired
	ResourceManager<ResourceEntity,PageParam> resourceManager;
	

	
	@Transactional
	@JEEService(commandId=Constants.COMMAND_SAVE,name="保存用户信息")
	@JEEResultConvert(convertClass=EntityToIdConvert.class)
	@Override
	public UserEntity save(UserEntity t) {
		if(t == null){
			throw new JEEException(JEEException.PARAM_IS_NULL);
		}
		String userName = t.getUserName();
		if(StringUtils.isEmpty(userName)){
			throw new JEEException(getServiceClassCode()+"15");
		}
		//校验用户名
		String hql = "select count(*) from  UserEntity e where e.userName = ?";
		List<Object> values = new ArrayList<Object>();
		values.add(userName);
		Long count = (Long)getSingleResult(hql, values);
		if(count>0){
			throw new JEEException(getServiceClassCode()+"14");
		}
		Set<RoleEntity> tempRoles = t.getRoles();
		if(tempRoles != null){
			Set<RoleEntity> roles = new HashSet<RoleEntity>();
			t.setRoles(roles);
			for(RoleEntity role: tempRoles){
				String roleId = role.getId();
				RoleEntity roleEntity = (RoleEntity) this.get(RoleEntity.class, roleId);
				if(roleEntity != null){
					roles.add(roleEntity);
				}else{
					LOGGER.warn("RoleEntity id=\""+roleId+"\"  can't find ");
				}
			}
		}
		
		Set<PostEntity>  tempPosts = t.getPosts();
		if(tempPosts != null){
			Set<PostEntity> posts = new HashSet<PostEntity>();
			t.setPosts(posts);
			for(PostEntity post: tempPosts){
				String postId = post.getId();
				PostEntity postEntity = (PostEntity) this.get(PostEntity.class, postId);
				if(postEntity != null){
					posts.add(postEntity);
				}else{
					LOGGER.warn("PostEntity id=\""+postId+"\"  can't find ");
				}
			}
		}
		OrgEntity org = t.getOrg();
		if(org != null){
			String orgId = org.getId();
			org = (OrgEntity) this.get(OrgEntity.class, orgId);
			t.setOrg(org);
		}
		return super.save(t);
	}
	
	
	@Transactional
	@JEEService(commandId=Constants.COMMAND_UPDATE,name="修改用户信息")
	@Override
	public UserEntity update(UserEntity t) {
		if(t == null){
			throw new JEEException(JEEException.PARAM_IS_NULL);
		}
		String id = t.getId();
		if(StringUtils.isEmpty(id)){
			throw new JEEException(JEEException.OBJECT_ID_IS_NULL);
		}
		UserEntity oldUserEntity = this.get(id);
		if(oldUserEntity == null){
			throw new JEEException(JEEException.CANT_NOT_FIND_RECORD);
		}
		String userName = t.getUserName();
		if(StringUtils.isEmpty(userName)){
			throw new JEEException(getServiceClassCode()+"15");
		}
		//校验用户名
		String hql = "select count(*) from  UserEntity e where e.userName = ? and e.id <> ?";
		List<Object> values = new ArrayList<Object>();
		values.add(userName);
		values.add(id);
		Long count = (Long)getSingleResult(hql, values);
		if(count>0){
			throw new JEEException(getServiceClassCode()+"14");
		}
		Set<RoleEntity> tempRoles = t.getRoles();
		if(tempRoles != null){
			Set<RoleEntity> roles = new HashSet<RoleEntity>();
			oldUserEntity.setRoles(roles);
			for(RoleEntity role: tempRoles){
				String roleId = role.getId();
				RoleEntity roleEntity = (RoleEntity) this.get(RoleEntity.class, roleId);
				if(roleEntity != null){
					roles.add(roleEntity);
				}else{
					LOGGER.warn("RoleEntity id=\""+roleId+"\"  can't find ");
				}
			}
		}
		
		Set<PostEntity>  tempPosts = t.getPosts();
		if(tempPosts != null){
			Set<PostEntity> posts = new HashSet<PostEntity>();
			oldUserEntity.setPosts(posts);
			for(PostEntity post: tempPosts){
				String postId = post.getId();
				PostEntity postEntity = (PostEntity) this.get(PostEntity.class, postId);
				if(postEntity != null){
					posts.add(postEntity);
				}else{
					LOGGER.warn("PostEntity id=\""+postId+"\"  can't find ");
				}
			}
		}
		OrgEntity org = t.getOrg();
		if(org != null){
			String orgId = org.getId();
			org = (OrgEntity) this.get(OrgEntity.class, orgId);
		}
		oldUserEntity.setOrg(org);
		return super.update(oldUserEntity);
	}
	
	@JEEService(commandId=Constants.JEE_COMMON_CODE_FIRST,name="用户登录",needCheckAuthority=false)
	public LoginResult login(LoginParam param){
		UserEntity  userEntity = verifyLoginParam(param);
		LoginResult loginResult = new LoginResult();
		loginResult.setRealName(userEntity.getRealName());
		OrgEntity org = userEntity.getOrg();
		if(org != null){
			loginResult.setOrgName(org.getName());
		}
		List<ResourceEntity> resources = resourceManager.queryResourceByUserId(userEntity.getId());
		buildMenuTree(loginResult,resources);
		return loginResult;
	}
	
	@Override
	public String getServiceClassCode() {
		return Constants.JEE_SYSTEM_CODE+"_"+Constants.JEE_SECURITY_CODE+"_"+CODE+"_";
	}
	
	protected UserEntity verifyLoginParam(LoginParam param){
		if(param == null){
			throw new JEEException(JEEException.PARAM_IS_NULL);
		}
		String hql = " from UserEntity e where e.userName = ? ";
		List<Object> values = new ArrayList<Object>();
		values.add(param.getUserName());
		UserEntity userEntity = this.queryUnique(hql, values);
		if(userEntity == null){
			throw new JEEException(this.getServiceClassCode()+Constants.JEE_COMMON_CODE_FIRST);
		}
		if(!userEntity.getEnabled()){
			throw new JEEException(this.getServiceClassCode()+Constants.JEE_COMMON_CODE_SECOND);
		}
		if(!userEntity.getPassword().equals(param.getPassword())){
			throw new JEEException(this.getServiceClassCode()+Constants.JEE_COMMON_CODE_THIRD);
		}
		return userEntity;
	}
	
	void buildMenuTree(LoginResult result ,List<ResourceEntity> resources){
		
		if(resources != null){
			List<String> commonds = result.getCommonds();
			if(commonds == null){
				commonds = new ArrayList<String>();
				result.setCommonds(commonds);
			}
			
			List<TreeNode> menus = result.getMenus();
			if(menus == null){
				menus = new ArrayList<TreeNode>();
				result.setMenus(menus);
			}
			Map<String,MenuNode> temp = new LinkedHashMap<String,MenuNode>();
			for(ResourceEntity resourceEntity : resources){
				if(resourceEntity.getResourceType() == ResourceTypeEnum.COMMAND){
					commonds.add(resourceEntity.getCode());
				}else{
					String id = resourceEntity.getId();
					MenuNode menu = temp.get(id);
					if(menu == null){
						menu = new MenuNode();
						menu.setId(id);
						menu.setViewName(resourceEntity.getViewName());
						menu.setExpanded(true);
						menu.setText(resourceEntity.getName());
						temp.put(id, menu);
					}
					
					ResourceEntity parent = resourceEntity.getParent();
					if(parent == null){
						menus.add(menu);
					}else{
						String parentId = parent.getId();
						TreeNode parentMenu = temp.get(parentId);
						if(parentMenu == null){
							menu = new MenuNode();
							menu.setExpanded(true);
							id = resourceEntity.getId();
							menu.setViewName(resourceEntity.getViewName());
							temp.put(id, menu);
							menu.setId(id);
							menu.setText(resourceEntity.getName());
							temp.put(id, menu);
						}
						List<Tree> children = parentMenu.getChildren();
						if(children == null){
							children = new ArrayList<Tree>();
							parentMenu.setChildren(children);
						}
						children.add(menu);
					}
				}
			}
			Collection<MenuNode> menuNodes = temp.values();
			if(menuNodes != null){
				for(MenuNode menuNode : menuNodes){
					List<Tree> children = menuNode.getChildren();
					if(children != null && !children.isEmpty()){
						menuNode.setLeaf(false);
						menuNode.setExpanded(true);
					}else{	
						menuNode.setLeaf(true);
					}
				}
			}
		}
	}
}
